import * as THREE from 'three';
import { Debug } from '../utils/Debug';
import { Explosion } from '../components/Explosion';

export type ProjectileSource = 'player' | 'enemy';

export class Projectile {
  // Three.js 相关
  private scene: THREE.Scene;
  private projectileMesh: THREE.Mesh;
  private trail: THREE.Points | null = null;
  
  // 位置和方向
  private position: THREE.Vector3;
  private direction: THREE.Vector3;
  private speed: number;
  
  // 投射物属性
  private radius: number = 0.3;
  private source: ProjectileSource;
  private damage: number;
  private lifetime: number = 5.0;
  private active: boolean = true;
  
  // 轨迹效果
  private trailPoints: THREE.Vector3[] = [];
  private maxTrailPoints: number = 20;
  
  constructor(
    scene: THREE.Scene,
    position: THREE.Vector3,
    direction: THREE.Vector3,
    source: ProjectileSource = 'player',
    damage: number = 25,
    speed: number = 30
  ) {
    this.scene = scene;
    this.position = position.clone();
    this.direction = direction.normalize();
    this.source = source;
    this.damage = damage;
    this.speed = speed;
    
    // 创建投射物模型
    this.createProjectile();
    
    // 创建轨迹效果
    this.createTrail();
    
    Debug.log(`创建了增强版${source === 'player' ? '玩家' : '敌人'}投射物`);
  }
  
  private createProjectile(): void {
    // 创建投射物几何体 - 增加炮弹大小
    const geometry = new THREE.SphereGeometry(this.radius * 2.5, 12, 12);
    
    // 根据来源选择不同颜色，增加颜色亮度
    const color = this.source === 'player' ? 0x22aaff : 0xff5500;
    
    // 创建发光材质 - 增强发光效果
    const material = new THREE.MeshStandardMaterial({
      color: color,
      emissive: color,
      emissiveIntensity: 3.0, // 进一步增强发光强度
      metalness: 0.8,
      roughness: 0.2
    });
    
    // 创建网格
    this.projectileMesh = new THREE.Mesh(geometry, material);
    this.projectileMesh.position.copy(this.position);
    this.projectileMesh.castShadow = true;
    
    // 添加点光源使投射物发光 - 增加光照范围和强度
    const light = new THREE.PointLight(color, 4, 6); // 再次增加光照强度和范围
    light.position.set(0, 0, 0);
    this.projectileMesh.add(light);
    
    // 添加到场景
    this.scene.add(this.projectileMesh);
  }
  
  private createTrail(): void {
    // 初始化轨迹点
    this.trailPoints.push(this.position.clone());
    
    // 创建轨迹点几何体
    const trailGeometry = new THREE.BufferGeometry();
    const positions = new Float32Array(this.maxTrailPoints * 3);
    trailGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    
    // 创建轨迹材质 - 进一步增加轨迹大小和亮度
    const trailMaterial = new THREE.PointsMaterial({
        color: this.source === 'player' ? 0x22aaff : 0xff5500,
        size: 1.5, // 增大轨迹点大小
        transparent: true,
        opacity: 1.0,
        blending: THREE.AdditiveBlending,
        sizeAttenuation: true,
        vertexColors: true // 启用顶点颜色
    });
    
    // 创建轨迹点
    this.trail = new THREE.Points(trailGeometry, trailMaterial);
    this.scene.add(this.trail);
    
    // 确保轨迹在一段时间后自动消失
    this.lifetime = Math.min(this.lifetime, 2.0); // 限制最大生命周期为2秒
  }
  
  public update(deltaTime: number): boolean {
    if (!this.active) return false;
    
    // 更新生命周期
    this.lifetime -= deltaTime;
    if (this.lifetime <= 0) {
      this.dispose();
      return false;
    }
    
    // 移动投射物
    const moveAmount = this.speed * deltaTime;
    this.position.add(this.direction.clone().multiplyScalar(moveAmount));
    
    // 更新网格位置
    this.projectileMesh.position.copy(this.position);
    
    // 更新轨迹
    this.updateTrail();
    
    return true;
  }
  
  private updateTrail(): void {
    // 添加新的轨迹点
    this.trailPoints.unshift(this.position.clone());
    
    // 限制轨迹点数量
    if (this.trailPoints.length > this.maxTrailPoints) {
      this.trailPoints.pop();
    }
    
    // 更新轨迹几何体
    const positions = new Float32Array(this.maxTrailPoints * 3);
    
    for (let i = 0; i < this.trailPoints.length; i++) {
      const point = this.trailPoints[i];
      positions[i * 3] = point.x;
      positions[i * 3 + 1] = point.y;
      positions[i * 3 + 2] = point.z;
    }
    
    // 更新轨迹点
    if (this.trail) {
      const geometry = this.trail.geometry;
      geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
      
      // 淡出轨迹末端，让轨迹更明显
      const colors = new Float32Array(this.maxTrailPoints * 3);
      const color = this.source === 'player' ? 
        new THREE.Color(0x22aaff) : 
        new THREE.Color(0xff5500);
      
      for (let i = 0; i < this.trailPoints.length; i++) {
        // 使用线性衰减，保持前段轨迹更明亮
        const alpha = 1 - i / this.trailPoints.length;
        colors[i * 3] = color.r * alpha;
        colors[i * 3 + 1] = color.g * alpha;
        colors[i * 3 + 2] = color.b * alpha;
      }
      
      geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
      (this.trail.material as THREE.PointsMaterial).vertexColors = true;
    }
  }
  
  public getPosition(): THREE.Vector3 {
    return this.position.clone();
  }
  
  public getRadius(): number {
    return this.radius;
  }
  
  public getSource(): ProjectileSource {
    return this.source;
  }
  
  public getDamage(): number {
    return this.damage;
  }
  
  public isActive(): boolean {
    return this.active;
  }
  
  /**
   * 检查投射物是否与指定的碰撞体发生碰撞
   * @param collider 要检测碰撞的碰撞体
   * @returns 是否发生碰撞
   */
  public checkCollision(collider: any): boolean {
    // 简单的球形碰撞检测
    if (!collider || !this.active) return false;
    
    // 获取碰撞体的位置
    const colliderPosition = collider.position;
    if (!colliderPosition) return false;
    
    // 计算距离
    const distance = this.position.distanceTo(colliderPosition);
    
    // 获取碰撞体的尺寸
    const colliderSize = collider.size;
    if (!colliderSize) return false;
    
    // 计算最小碰撞距离
    const minDistance = this.radius + Math.max(colliderSize.x, colliderSize.z) / 2;
    
    // 如果距离小于最小碰撞距离，则发生碰撞
    return distance < minDistance;
  }
  
  public hitTarget(): void {
    // 创建爆炸效果
    this.createExplosion();
    
    // 标记为不活跃
    this.active = false;
    
    // 清理资源
    this.dispose();
  }
  
  private createExplosion(): void {
    try {
      // 创建一个临时的爆炸效果，不使用Explosion类以避免资源泄漏
      const explosionGroup = new THREE.Group();
      this.scene.add(explosionGroup);
      
      // 创建爆炸光源
      const light = new THREE.PointLight(
        this.source === 'player' ? 0x22aaff : 0xff5500,
        3,
        5
      );
      light.position.copy(this.position);
      explosionGroup.add(light);
      
      // 创建爆炸粒子
      for (let i = 0; i < 10; i++) {
        const size = Math.random() * 0.2 + 0.1;
        const geometry = new THREE.SphereGeometry(size, 6, 6);
        const material = new THREE.MeshBasicMaterial({
          color: this.source === 'player' ? 0x22aaff : 0xff5500,
          transparent: true,
          opacity: 0.8
        });
        
        const particle = new THREE.Mesh(geometry, material);
        
        // 随机位置和方向
        const angle = Math.random() * Math.PI * 2;
        const radius = Math.random() * 0.5;
        particle.position.set(
          this.position.x + Math.cos(angle) * radius,
          this.position.y + Math.random() * 0.5,
          this.position.z + Math.sin(angle) * radius
        );
        
        explosionGroup.add(particle);
      }
      
      // 定时清理爆炸效果
      setTimeout(() => {
        // 移除所有粒子
        while (explosionGroup.children.length > 0) {
          const child = explosionGroup.children[0];
          explosionGroup.remove(child);
          if (child instanceof THREE.Mesh && child.geometry) {
            child.geometry.dispose();
            if (child.material) {
              if (Array.isArray(child.material)) {
                child.material.forEach(m => m.dispose());
              } else {
                child.material.dispose();
              }
            }
          }
          if (child instanceof THREE.Light) {
            child.dispose();
          }
        }
        // 移除爆炸组
        this.scene.remove(explosionGroup);
      }, 500); // 500毫秒后清理
      
      Debug.log(`投射物爆炸 (${this.position.x.toFixed(1)}, ${this.position.y.toFixed(1)}, ${this.position.z.toFixed(1)})`);
    } catch (error) {
      Debug.error(`创建爆炸效果时出错: ${error}`);
    }
  }
  
  public dispose(): void {
    try {
      // 立即标记为不活跃，防止多次调用
      if (!this.active) return;
      this.active = false;
      
      // 从场景中移除投射物网格
      if (this.projectileMesh) {
        // 移除附加到projectileMesh的所有灯光
        for (let i = this.projectileMesh.children.length - 1; i >= 0; i--) {
          const child = this.projectileMesh.children[i];
          if (child instanceof THREE.Light) {
            this.projectileMesh.remove(child);
            child.dispose();
          }
        }
        
        // 移除投射物网格
        this.scene.remove(this.projectileMesh);
        
        // 清理几何体和材质
        if (this.projectileMesh.geometry) this.projectileMesh.geometry.dispose();
        if (this.projectileMesh.material) {
          if (Array.isArray(this.projectileMesh.material)) {
            this.projectileMesh.material.forEach(material => material.dispose());
          } else {
            this.projectileMesh.material.dispose();
          }
        }
        
        // 解除引用
        this.projectileMesh = null;
      }
      
      // 从场景中移除轨迹
      if (this.trail) {
        this.scene.remove(this.trail);
        
        // 清理几何体和材质
        if (this.trail.geometry) this.trail.geometry.dispose();
        if (this.trail.material) {
          if (Array.isArray(this.trail.material)) {
            this.trail.material.forEach(material => material.dispose());
          } else {
            this.trail.material.dispose();
          }
        }
        
        // 解除引用
        this.trail = null;
      }
      
      // 清空轨迹点数组
      this.trailPoints = [];
      
      Debug.log('投射物资源已彻底清理');
    } catch (error) {
      Debug.error(`清理投射物资源时出错: ${error}`);
    }
  }
} 